package kz.pompei.OneGwt.client.personrole.impl;

import static kz.pompei.OneGwt.cmodel.CommonUtil.isDefined;
import static kz.pompei.OneGwt.cmodel.CommonUtil.isEmpty;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import kz.pompei.OneGwt.client.personrole.RoleListMed;
import kz.pompei.OneGwt.client.personrole.RoleListView;
import kz.pompei.OneGwt.cmodel.SimpleRecord;
import kz.pompei.OneGwt.ifaces.util.Comeback;
import kz.pompei.OneGwt.ifaces.util.Handler;
import kz.pompei.OneGwt.ifaces.widget.StateMessage;
import kz.pompei.OneGwt.remote.PersonroleManagerServiceAsync;

public class RoleListMedImpl implements RoleListMed {
  private RoleListView view;
  private PersonroleManagerServiceAsync service;
  private boolean initialized = false;
  private String personId;
  
  private final List<SimpleRecord> roleList = new ArrayList<SimpleRecord>();
  private final Set<String> personRoleIds = new HashSet<String>();
  
  private SimpleRecord findRoleRecord(String roleId) {
    if (roleId == null) return null;
    for (SimpleRecord r : roleList) {
      if (roleId.equals( r.getId() )) return r;
    }
    return null;
  }
  
  public void setView(RoleListView view) {
    this.view = view;
  }
  
  public void setService(PersonroleManagerServiceAsync service) {
    this.service = service;
  }
  
  private void initialize() {
    if (initialized) return;
    defineEventHandlers();
    initialized = true;
  }
  
  private void defineEventHandlers() {
    view.comboApplication().addChangeSelectionHandler( new Handler() {
      @Override
      public void handle() {
        comboApplicationChanged();
      }
    } );
    
    {
      Handler handler = new Handler() {
        @Override
        public void handle() {
          updateToBtnsEnability();
        }
      };
      view.listLeft().addChangeSelectionHandler( handler );
      view.listRight().addChangeSelectionHandler( handler );
    }
    
    view.buttonToLeft().addClickHandler( new Handler() {
      @Override
      public void handle() {
        final String roleId = view.listRight().getSelectedId();
        if (isEmpty( roleId )) return;
        service.addRole( personId, getApplicationId(), roleId, new Comeback<Void>() {
          @Override
          protected void result(Void result) {
            view.buttonToLeft().setEnabled( false );
            personRoleIds.add( roleId );
            view.listLeft().addOrUpdate( findRoleRecord( roleId ) );
            view.listRight().removeById( roleId );
            updateToBtnsEnability();
          }
        } );
      }
    } );
    
    view.buttonToRight().addClickHandler( new Handler() {
      @Override
      public void handle() {
        view.buttonToRight().setEnabled( false );
        final String roleId = view.listLeft().getSelectedId();
        if (isEmpty( roleId )) return;
        service.deleteRole( personId, getApplicationId(), roleId, new Comeback<Void>() {
          @Override
          protected void result(Void result) {
            personRoleIds.remove( roleId );
            view.listRight().addOrUpdate( findRoleRecord( roleId ) );
            view.listLeft().removeById( roleId );
            updateToBtnsEnability();
          }
        } );
      }
    } );
  }
  
  private String getApplicationId() {
    return view.comboApplication().getSelectedId();
  }
  
  @Override
  public void refresh() {
    initialize();
    this.personId = null;
    
    view.comboApplication().clean();
    view.listLeft().clean();
    view.listRight().clean();
    
    view.comboApplication().setStateMessage( StateMessage.WAIT );
    view.listLeft().setStateMessage( StateMessage.WAIT );
    view.listRight().setStateMessage( StateMessage.WAIT );
    
    view.buttonToLeft().setEnabled( false );
    view.buttonToRight().setEnabled( false );
    
    service.getApplicationList( new Comeback<List<SimpleRecord>>() {
      @Override
      protected void beforeCome() {
        view.comboApplication().setStateMessage( StateMessage.EMPTY );
        view.listLeft().setStateMessage( StateMessage.USER1 );
        view.listRight().setStateMessage( StateMessage.USER1 );
      }
      
      @Override
      protected void result(List<SimpleRecord> result) {
        view.comboApplication().set( result );
        view.comboApplication().select( null );
      }
    } );
  }
  
  private void comboApplicationChanged() {
    String applicationId = view.comboApplication().getSelectedId();
    if (isEmpty( applicationId )) {
      view.listLeft().setStateMessage( StateMessage.USER1 );
      view.listRight().setStateMessage( StateMessage.USER1 );
      return;
    }
    
    view.listLeft().setStateMessage( StateMessage.WAIT );
    view.listRight().setStateMessage( StateMessage.WAIT );
    roleList.clear();
    
    service.getRoleList( applicationId, new Comeback<List<SimpleRecord>>() {
      @Override
      protected void beforeCome() {
        view.listLeft().setStateMessage( StateMessage.USER2 );
        view.listRight().setStateMessage( StateMessage.EMPTY );
        roleList.clear();
      }
      
      @Override
      protected void result(List<SimpleRecord> result) {
        roleList.addAll( result );
        updateLeftList();
      }
    } );
  }
  
  @Override
  public void setPersonId(String personId) {
    this.personId = personId;
    updateLeftList();
  }
  
  private void defineRoleLists() {
    view.listLeft().clean();
    view.listRight().clean();
    for (SimpleRecord r : roleList) {
      if (personRoleIds.contains( r.getId() )) {
        view.listLeft().addOrUpdate( r );
      } else {
        view.listRight().addOrUpdate( r );
      }
    }
    if (isEmpty( personId )) {
      view.listLeft().setStateMessage( StateMessage.USER2 );
    }
  }
  
  private void updateLeftList() {
    personRoleIds.clear();
    defineRoleLists();
    
    view.buttonToRight().setEnabled( false );
    view.buttonToLeft().setEnabled( false );
    
    if (isEmpty( personId ) || isEmpty( getApplicationId() )) {
      return;
    }
    
    view.listLeft().setStateMessage( StateMessage.WAIT );
    
    service.getRoleIds( personId, getApplicationId(), new Comeback<Set<String>>() {
      @Override
      protected void beforeCome() {
        view.listLeft().setStateMessage( StateMessage.EMPTY );
      }
      
      @Override
      protected void result(Set<String> result) {
        personRoleIds.addAll( result );
        defineRoleLists();
        updateToBtnsEnability();
      }
    } );
  }
  
  private void updateToBtnsEnability() {
    if (isEmpty( personId ) || isEmpty( getApplicationId() )) {
      view.buttonToRight().setEnabled( false );
      view.buttonToLeft().setEnabled( false );
      return;
    }
    
    view.buttonToRight().setEnabled( isDefined( view.listLeft().getSelectedId() ) );
    view.buttonToLeft().setEnabled( isDefined( view.listRight().getSelectedId() ) );
  }
}
